package sqlengine.queryOptimization;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import org.junit.Test;

import sqlengine.conditions.ConditionExecption;
import sqlengine.conditions.Conditions;
import sqlengine.database.DataFile;
import sqlengine.database.DataManager;

public class PlanOptimizerTest {

	@Test
	public void testGenerateOptimizedPlan() {
		// create one table
		// A(a,b,c)
		// index on a
		// condition: a="abc", b="bcd",c="cde",d=e
		try {
			String fileName = "A";
			Map<String, Integer> descriptor = new HashMap<String, Integer>();
			descriptor.put("a", 50);
			descriptor.put("b", 50);
			descriptor.put("c", 50);
			descriptor.put("d", 50);
			descriptor.put("e", 50);
			DataFile dataFile = DataManager.createFile(fileName, descriptor);
			dataFile.createIndex("_A.a", "a");
			Conditions condition = new Conditions("A");
			condition.addConditions("A", "c", "cde");
			condition.addConditions("A", "a", "abc");
			condition.addConditions("A", "b", "bcd");
			condition.addConditions("A", "d","A","e");
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			assertEquals("column a",result[0],"a");
			assertEquals("value: abc",result[1],"abc");
			assertEquals("column c","c",condition.getConditions().get(0).get(0));
			assertEquals("value: cde","cde",condition.getConditions().get(0).get(1));
			assertEquals("column b","b",condition.getConditions().get(0).get(2));
			assertEquals("value: bcd","bcd",condition.getConditions().get(0).get(3));
			assertEquals("condition size should be 4",4,condition.getConditions().get(0).size());
			assertEquals("two column conditions","d",condition.getConditions().get(1).get(0));
			assertEquals("two column conditions","e",condition.getConditions().get(1).get(1));
			assertEquals("two column condition size should be 2",2,condition.getConditions().get(1).size());
			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create one table
		// A(a,b,c)
		// condition: a="abc", b="bcd",c="cde"
		try {
			String fileName = "A";
			Map<String, Integer> descriptor = new HashMap<String, Integer>();
			descriptor.put("a", 50);
			descriptor.put("b", 50);
			descriptor.put("c", 50);
			DataFile dataFile = DataManager.createFile(fileName, descriptor);
			Conditions condition = new Conditions("A");
			condition.addConditions("A", "c", "cde");
			condition.addConditions("A", "a", "abc");
			condition.addConditions("A", "b", "bcd");
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			assertNull("result should be null",result);
			assertEquals("column c","c",condition.getConditions().get(0).get(0));
			assertEquals("value: cde","cde",condition.getConditions().get(0).get(1));
			assertEquals("column a","a",condition.getConditions().get(0).get(2));
			assertEquals("value: abc","abc",condition.getConditions().get(0).get(3));
			assertEquals("column b","b",condition.getConditions().get(0).get(4));
			assertEquals("value: bcd","bcd",condition.getConditions().get(0).get(5));
			assertEquals("condition size should be 6",6,condition.getConditions().get(0).size());
			assertEquals("two column condition size should be 0",0,condition.getConditions().get(1).size());
			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c,d)
		// index on A.a,A.b,A.c
		// index on B.a,B.b
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			dataFileA.createIndex("_A.a", "a");
			dataFileA.createIndex("_A.b", "b");
			dataFileA.createIndex("_A.c", "c");
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			dataFileB.createIndex("_B.a", "a");
			dataFileB.createIndex("_B.b", "b");
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			assertEquals("table A",result[0],"A");
			assertEquals("column a",result[1],"a");
			assertEquals("table B",result[2],"B");
			assertEquals("column a",result[3],"a");

			// A.b = "A.b"
			assertEquals("A.b = \"A.b\"","b",condition.getConditions().get(0).get(0));
			assertEquals("value: A.b","A.b",condition.getConditions().get(0).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("B.b = \"B.b\"","b",condition.getConditions().get(1).get(0));
			assertEquals("value: B.b","B.b",condition.getConditions().get(1).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(1).size());
			// A.c = B.c
			assertEquals("A.c","c",condition.getConditions().get(2).get(0));
			assertEquals("B.c","c",condition.getConditions().get(2).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c)
		// index on A.b,A.c
		// index on B.b
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			dataFileA.createIndex("_A.b", "b");
			dataFileA.createIndex("_A.c", "c");
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			dataFileB.createIndex("_B.b", "b");
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			assertEquals("size 6",6,result.length);
			assertEquals("table A",result[0],"A");
			assertEquals("column b",result[1],"b");
			assertEquals("value: A.b",result[2],"A.b");
			assertEquals("table B",result[3],"B");
			assertEquals("column b",result[4],"b");
			assertEquals("value: B.b",result[5],"B.b");

			// A.b = "A.b"
			assertEquals("condition size should be 0",0,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("condition size should be 0",0,condition.getConditions().get(1).size());
			// A.a = B.a
			// A.c = B.c
			assertEquals("A.a","a",condition.getConditions().get(2).get(0));
			assertEquals("B.a","a",condition.getConditions().get(2).get(1));
			assertEquals("A.c","c",condition.getConditions().get(2).get(2));
			assertEquals("B.c","c",condition.getConditions().get(2).get(3));
			assertEquals("condition size should be 4",4,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c)
		// index on A.c
		// index on B.b
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			dataFileA.createIndex("_A.c", "c");
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			dataFileB.createIndex("_B.b", "b");
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			// A.c = B.c
			assertEquals("size 5",5,result.length);
			assertEquals("table A",result[0],"A");
			assertEquals("column c",result[1],"c");
			assertEquals("table B",result[2],"B");
			assertEquals("column c",result[3],"c");
			assertEquals("first",result[4],"first");

			// A.b = "A.b"
			assertEquals("A.b = \"A.b\"","b",condition.getConditions().get(0).get(0));
			assertEquals("value: A.b","A.b",condition.getConditions().get(0).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("B.b = \"B.b\"","b",condition.getConditions().get(1).get(0));
			assertEquals("value: B.b","B.b",condition.getConditions().get(1).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(1).size());
			// A.a = B.a
			assertEquals("A.a","a",condition.getConditions().get(2).get(0));
			assertEquals("B.a","a",condition.getConditions().get(2).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c)
		// index on B.b
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			dataFileB.createIndex("_B.b", "b");
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			// A.c = B.c
			assertEquals("size 3",3,result.length);
			assertEquals("table B",result[0],"B");
			assertEquals("column b",result[1],"b");
			assertEquals("value B.b",result[2],"B.b");

			// A.b = "A.b"			
			assertEquals("A.b = \"A.b\"","b",condition.getConditions().get(0).get(0));
			assertEquals("value: A.b","A.b",condition.getConditions().get(0).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("condition size should be 0",0,condition.getConditions().get(1).size());
			// A.a = B.a
			assertEquals("A.a","a",condition.getConditions().get(2).get(0));
			assertEquals("B.a","a",condition.getConditions().get(2).get(1));
			assertEquals("A.c","c",condition.getConditions().get(2).get(2));
			assertEquals("B.c","c",condition.getConditions().get(2).get(3));
			assertEquals("condition size should be 4",4,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c)
		// index on A.b
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			dataFileA.createIndex("_A.b", "b");
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			// A.c = B.c
			assertEquals("size 3",3,result.length);
			assertEquals("table A",result[0],"A");
			assertEquals("column b",result[1],"b");
			assertEquals("value A.b",result[2],"A.b");

			// A.b = "A.b"			

			assertEquals("condition size should be 0",0,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("condition size should be 2",2,condition.getConditions().get(1).size());
			assertEquals("B.b = \"B.b\"","b",condition.getConditions().get(1).get(0));
			assertEquals("value: B.b","B.b",condition.getConditions().get(1).get(1));
			// A.a = B.a
			assertEquals("A.a","a",condition.getConditions().get(2).get(0));
			assertEquals("B.a","a",condition.getConditions().get(2).get(1));
			assertEquals("A.c","c",condition.getConditions().get(2).get(2));
			assertEquals("B.c","c",condition.getConditions().get(2).get(3));
			assertEquals("condition size should be 4",4,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		
		// create two tables A,B
		// A(a,b,c,d)
		// B(a,b,c)
		// A.a = B.a
		// A.b = "A.b"
		// B.b = "B.b"
		// A.c = B.c
		// A.c = A.d
		// B.c = B.d
		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("a", 50);
			descriptorA.put("b", 50);
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("a", 50);
			descriptorB.put("b", 50);
			descriptorB.put("c", 50);
			descriptorB.put("d", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);
			
			
			Conditions condition = new Conditions("A","B");
			
			condition.addConditions("A", "a", "B","a");
			condition.addConditions("A", "b", "A.b");
			condition.addConditions("B", "b", "B.b");
			condition.addConditions("A", "c", "B","c");
			condition.addConditions("A", "c", "A","d");
			condition.addConditions("B", "c", "B","d");
			
			PlanOptimizer planOptimizer = new PlanOptimizer(condition);
			planOptimizer.checkConsistency();
			String[] result = planOptimizer.generateOptimizedPlan();
			// A.c = B.c
			assertNull(result);

			// A.b = "A.b"			
			assertEquals("A.b = \"A.b\"","b",condition.getConditions().get(0).get(0));
			assertEquals("value: A.b","A.b",condition.getConditions().get(0).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(0).size());
			// B.b = "B.b"
			assertEquals("condition size should be 2",2,condition.getConditions().get(1).size());
			assertEquals("B.b = \"B.b\"","b",condition.getConditions().get(1).get(0));
			assertEquals("value: B.b","B.b",condition.getConditions().get(1).get(1));
			// A.a = B.a
			assertEquals("A.a","a",condition.getConditions().get(2).get(0));
			assertEquals("B.a","a",condition.getConditions().get(2).get(1));
			assertEquals("A.c","c",condition.getConditions().get(2).get(2));
			assertEquals("B.c","c",condition.getConditions().get(2).get(3));
			assertEquals("condition size should be 4",4,condition.getConditions().get(2).size());
			// A.c = A.d
			assertEquals("A.c","c",condition.getConditions().get(3).get(0));
			assertEquals("A.d","d",condition.getConditions().get(3).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(3).size());
			// B.c = B.d
			assertEquals("B.c","c",condition.getConditions().get(4).get(0));
			assertEquals("B.d","d",condition.getConditions().get(4).get(1));
			assertEquals("condition size should be 2",2,condition.getConditions().get(4).size());

			DataManager.exit();
		} catch (ConditionExecption e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
		catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("should not throw exception");
		}
	}

	@Test
	public void testCheckConsistency() {
		// test contradict conditions
		// assume table A,B
		// assume conditions: A.c = B.c, A.c = "12", B.c = "23"

		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("c", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("c", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);

			Conditions conditions = new Conditions("A", "B");
			conditions.addConditions("A", "c", "B", "c");
			conditions.addConditions("A", "c", "12");
			conditions.addConditions("B", "c", "23");
			PlanOptimizer planOptimizer = new PlanOptimizer(conditions);
			planOptimizer.checkConsistency();
			fail("check inconsistency");
		} catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			assertEquals("", "exist non-consistent conditions", e.getMessage());
			DataManager.exit();
		} catch (ConditionExecption e2) {
			// TODO Auto-generated catch block
			System.out.println(e2.getMessage());
			fail("should not throw exception");
		}

		// test correct conditions decomposition
		// assume table A,B
		// assume conditions: A.c = B.c, A.c = "12"
		// after check consistency, conditions: A.c = "12", B.c = "12"

		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("c", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("c", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);

			Conditions conditions = new Conditions("A", "B");
			conditions.addConditions("A", "c", "B", "c");
			conditions.addConditions("A", "c", "12");
			PlanOptimizer planOptimizer = new PlanOptimizer(conditions);
			planOptimizer.checkConsistency();
			assertEquals("c", conditions.getConditions().get(0).get(0));
			assertEquals("12", conditions.getConditions().get(0).get(1));
			assertEquals("c", conditions.getConditions().get(1).get(0));
			assertEquals("12", conditions.getConditions().get(1).get(1));
			assertEquals(0, conditions.getConditions().get(2).size());
			DataManager.exit();
		} catch (ConditionExecption e1) {
			// TODO Auto-generated catch block
			System.out.println(e1.getMessage());
			fail("should not throw exception");
		} catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("check consistent conditions");
		}

		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("c", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);

			Conditions conditions = new Conditions("A");
			conditions.addConditions("A", "c", "A", "d");
			conditions.addConditions("A", "c", "12");
			PlanOptimizer planOptimizer = new PlanOptimizer(conditions);
			planOptimizer.checkConsistency();
			assertEquals("c", conditions.getConditions().get(0).get(0));
			assertEquals("12", conditions.getConditions().get(0).get(1));
			assertEquals("d", conditions.getConditions().get(0).get(2));
			assertEquals("12", conditions.getConditions().get(0).get(3));
			DataManager.exit();
		} catch (ConditionExecption e1) {
			// TODO Auto-generated catch block
			System.out.println(e1.getMessage());
			fail("should not throw exception");
		} catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			fail("check consistent conditions");
		}

		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("c", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);

			Conditions conditions = new Conditions("A", "B");
			conditions.addConditions("A", "c", "A", "d");
			conditions.addConditions("A", "c", "12");
			conditions.addConditions("A", "c", "B", "c");
			conditions.addConditions("B", "c", "23");

			PlanOptimizer planOptimizer = new PlanOptimizer(conditions);
			planOptimizer.checkConsistency();
			fail("check inconsistency");

		} catch (ConditionExecption e1) {
			// TODO Auto-generated catch block
			System.out.println(e1.getMessage());
			fail("should not throw exception");
		} catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			assertEquals("", "exist non-consistent conditions", e.getMessage());
			DataManager.exit();
		}

		try {
			String fileNameA = "A";
			Map<String, Integer> descriptorA = new HashMap<String, Integer>();
			descriptorA.put("c", 50);
			descriptorA.put("d", 50);
			descriptorA.put("e", 50);
			descriptorA.put("g", 50);
			DataFile dataFileA = DataManager.createFile(fileNameA, descriptorA);
			
			String fileNameB = "B";
			Map<String, Integer> descriptorB = new HashMap<String, Integer>();
			descriptorB.put("c", 50);
			descriptorB.put("f", 50);
			descriptorB.put("h", 50);
			DataFile dataFileB = DataManager.createFile(fileNameB, descriptorB);

			Conditions conditions = new Conditions("A", "B");
			conditions.addConditions("A", "c", "A", "d");
			conditions.addConditions("A", "c", "12");
			conditions.addConditions("A", "c", "B", "c");
			conditions.addConditions("A", "d", "A", "e");
			conditions.addConditions("B", "c", "B", "f");
			conditions.addConditions("A", "g", "B", "h");

			PlanOptimizer planOptimizer = new PlanOptimizer(conditions);
			planOptimizer.checkConsistency();

			assertEquals("c", conditions.getConditions().get(1).get(0));
			assertEquals("12", conditions.getConditions().get(1).get(1));
			assertEquals("f", conditions.getConditions().get(1).get(2));
			assertEquals("12", conditions.getConditions().get(1).get(3));
			assertEquals(2, conditions.getConditions().get(2).size());
			assertEquals("g", conditions.getConditions().get(2).get(0));
			assertEquals("h", conditions.getConditions().get(2).get(1));
			assertEquals(0, conditions.getConditions().get(3).size());
			assertEquals(0, conditions.getConditions().get(4).size());
			assertEquals("c", conditions.getConditions().get(0).get(0));
			assertEquals("12", conditions.getConditions().get(0).get(1));
			assertEquals("d", conditions.getConditions().get(0).get(2));
			assertEquals("12", conditions.getConditions().get(0).get(3));
			assertEquals("e", conditions.getConditions().get(0).get(4));
			assertEquals("12", conditions.getConditions().get(0).get(5));

		} catch (ConditionExecption e1) {
			// TODO Auto-generated catch block
			System.out.println(e1.getMessage());
			e1.printStackTrace();
			fail("should not throw exception");
		} catch (QueryOptimizationException e) {
			// TODO Auto-generated catch block
			assertEquals("", "exist non-consistent conditions", e.getMessage());
			DataManager.exit();
		}
	}

}
